<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <title>JfireEL AI-Friendly API Documentation (Updated)</title>
    <style>
        body {
            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
            line-height: 1.6;
            color: #333;
            max-width: 960px;
            margin: 0 auto;
            padding: 20px;
        }
        h1, h2, h3 {
            border-bottom: 1px solid #eaecef;
            padding-bottom: 0.3em;
        }
        h1 { font-size: 2.5em; }
        h2 { font-size: 2em; }
        h3 { font-size: 1.5em; }
        code {
            font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
            background-color: #f6f8fa;
            padding: 0.2em 0.4em;
            margin: 0;
            font-size: 85%;
            border-radius: 3px;
        }
        pre {
            background-color: #f6f8fa;
            padding: 16px;
            overflow: auto;
            border-radius: 3px;
        }
        pre code {
            padding: 0;
            margin: 0;
            font-size: 100%;
            background-color: transparent;
        }
        .container {
            margin-top: 20px;
        }
        .api-section {
            margin-bottom: 40px;
        }
    </style>
</head>
<body>
    <h1>JfireEL AI-Friendly API 文档 (已更新)</h1>
    <div class="container">
        <h2>项目概述</h2>
        <p>
            JfireEL 是一个轻量级、高性能的Java表达式语言（Expression Language）引擎。它支持丰富的表达式语法，包括算术运算、逻辑运算、方法调用、属性访问以及基本的控制流。通过将表达式字符串解析为可执行的<code>Operand</code>对象，JfireEL可以高效地在运行时动态计算代码逻辑。
        </p>

        <div class="api-section">
            <h2>核心API</h2>
            <p>JfireEL框架主要由以下几个核心类组成：</p>
            
            <h3>1. <code>Expression</code> (静态工具类)</h3>
            <p>
                这是一个静态工具类，是使用JfireEL的主要入口。它提供了静态方法来解析表达式字符串、注册全局函数和类。
            </p>
            <p><strong>关键方法:</strong></p>
            <h4>1. 表达式解析 (Parsing)</h4>
            <ul>
                <li>
                    <code>public static Operand parse(String el)</code>:
                    <br>
                    在默认的Matrix上下文中解析表达式字符串，返回可执行的<code>Operand</code>对象。
                </li>
                <li>
                    <code>public static Operand parse(String el, String matrixName)</code>:
                    <br>
                    在指定名称的<code>Matrix</code>上下文中解析表达式。如果该名称的Matrix不存在，将使用默认的Matrix。
                </li>
                <li>
                    <code>public static Operand parse(String el, Matrix matrix)</code>:
                    <br>
                    在给定的<code>Matrix</code>实例中解析表达式，提供更灵活的上下文管理。
                </li>
                <li>
                    <code>public static Operand parse(String el, ELConfig config)</code>:
                    <br>
                    使用自定义的<code>ELConfig</code>配置，在默认Matrix中解析表达式。
                </li>
                <li>
                    <code>public static Operand parse(String el, String matrixName, ELConfig config)</code>:
                    <br>
                    使用自定义配置，在指定名称的<code>Matrix</code>中解析表达式。
                </li>
                <li>
                    <code>public static Operand parse(String el, Matrix matrix, ELConfig config)</code>:
                    <br>
                    最完整的解析方法，允许同时指定<code>Matrix</code>实例和<code>ELConfig</code>配置。
                </li>
            </ul>

            <h4>2. 功能注册 (Registration)</h4>
            <ul>
                <li>
                    <code>public static void registerClass(String name, Class&lt;?&gt; clazz)</code>:
                    <br>
                    在默认Matrix中注册一个类，之后可以在表达式中通过名称使用它。
                </li>
                <li>
                    <code>public static void registerClass(String name, Class&lt;?&gt; clazz, String matrixName)</code>:
                    <br>
                    将一个类注册到指定名称的<code>Matrix</code>中，实现作用域隔离。
                </li>
                <li>
                    <code>public static void registerFunctionCall(String functionBody)</code>:
                    <br>
                    在默认Matrix中注册一个或多个以EL语法写成的自定义函数。
                </li>
                <li>
                    <code>public static void registerFunctionCall(String functionBody, String matrixName)</code>:
                    <br>
                    将自定义函数注册到指定名称的<code>Matrix</code>中。
                </li>
                <li>
                    <code>public static void registerReferenceCall(String name, Method method)</code>:
                    <br>
                    将一个Java方法注册为可在EL中调用的引用函数（默认Matrix）。
                </li>
                <li>
                    <code>public static void registerReferenceCall(String name, Method method, String matrixName)</code>:
                    <br>
                    将引用函数注册到指定名称的<code>Matrix</code>中。
                </li>
                <li>
                    <code>public static void scanForReferenceCall(Class&lt;?&gt; clazz)</code>:
                    <br>
                    扫描一个类，自动将所有标注了<code>@ReferenceCall</code>注解的公共方法注册为EL函数。
                </li>
            </ul>

            <h4>3. 性能加速 (Acceleration)</h4>
            <ul>
                <li>
                    <code>public static void registerAcceleratorForPropertyRead(Field field, Function&lt;Object, Object&gt; accelerator)</code>:
                    <br>
                    为特定字段的属性读取注册一个加速器（Function），以替代反射，提升性能（默认Matrix）。
                </li>
                <li>
                    <code>public static void registerAcceleratorForPropertyRead(Field field, Function&lt;Object, Object&gt; accelerator, String matrixName)</code>:
                    <br>
                    将属性读取加速器注册到指定名称的<code>Matrix</code>中。
                </li>
                <li>
                    <code>public static void registerAcceleratorForMethodInvoke(Executable executable, MethodInvoker methodInvoker)</code>:
                    <br>
                    为特定方法（或构造函数）的调用注册一个<code>MethodInvoker</code>加速器（默认Matrix）。
                </li>
                <li>
                    <code>public static void registerAcceleratorForMethodInvoke(Executable executable, MethodInvoker methodInvoker, String matrixName)</code>:
                    <br>
                    将方法调用加速器注册到指定名称的<code>Matrix</code>中。
                </li>
            </ul>

            <h4>4. 代码格式化 (Formatting)</h4>
            <ul>
                <li>
                    <code>public static String format(String content)</code>:
                    <br>
                    对EL表达式代码进行美化格式化。它会自动处理换行和缩进，使代码更具可读性。
                </li>
            </ul>

            <h3>2. <code>Operand</code></h3>
            <p>
                <code>Operand</code> 代表一个已编译的、可执行的表达式。它是 <code>Expression.parse(...)</code> 方法的返回结果。
            </p>
            <p><strong>关键方法:</strong></p>
            <ul>
                <li>
                    <code>public Object calculate(Map<String, Object> vars)</code>:
                    <br>
                    在给定的<code>Map</code>变量环境中执行表达式，并返回计算结果。这个<code>Map</code>提供了表达式执行时所需的运行时变量。
                </li>
                 <li>
                    <code>public Object calculate()</code>:
                    <br>
                    执行一个不含外部变量的表达式。
                </li>
            </ul>

            <h3>3. <code>Matrix</code> (分层上下文)</h3>
            <p>
                <code>Matrix</code> 是JfireEL中一个至关重要的概念。它并非一个简单的变量容器，而是一个**分层的上下文环境**，用于隔离和管理函数、类和变量的作用域。
            </p>
            <p>
                通过将多个<code>Matrix</code>实例链接成一个父子关系的链条，可以构建出不同的作用域。当引擎在表达式中寻找一个函数或变量时，它会**从当前的<code>Matrix</code>开始查找，如果找不到，则会沿着父级链一直向上查找**，直到找到匹配项或到达最顶层的根<code>Matrix</code>。
            </p>
            <p>这种设计使得在不同作用域中定义同名但不同实现的函数成为可能，有效地避免了命名冲突，是实现词法作用域的关键。</p>
            <p>
                <strong>用法:</strong> 用户通常不需要直接创建或管理<code>Matrix</code>实例。相反，<code>Matrix</code>是在需要时，通过<code>Expression</code>的静态方法由JfireEL隐式创建和管理的。通过在以下方法中提供一个<code>matrixName</code>字符串，即可利用<code>Matrix</code>的上下文功能：
            </p>
            <ul>
                <li><code>Expression.parse(String text, String matrixName)</code></li>
                <li><code>Expression.registerFunctionCall(String functionBody, String matrixName)</code></li>
                <li><code>Expression.registerClass(String name, Class<?> clazz, String matrixName)</code></li>
            </ul>
            <p>当你为这些方法提供一个名称时，JfireEL会查找或创建一个同名的<code>Matrix</code>，从而将操作限定在该上下文中。</p>
        </div>

        <div class="api-section">
            <h2>用法示例</h2>

            <!-- 基本运算 -->
            <h3>1. 基本运算</h3>
            <h4>算术与逻辑运算</h4>
            <p>执行标准的数学和逻辑运算。</p>
            <h4>数字类型兼容性与自动提升</h4>
            <p>
                JfireEL在处理混合数字类型的运算时，遵循一套明确的自动类型提升规则，以确保精度和一致性。当不同类型的数字进行运算时，它们会被自动转换为范围更广的类型。规则优先级如下：
            </p>
            <ol>
                <li>
                    <strong>BigDecimal (最高优先级):</strong> 如果参与运算的任何一方是 <code>BigDecimal</code> 类型，另一方也会被转换为 <code>BigDecimal</code>，计算结果为 <code>BigDecimal</code>。这保证了最高的计算精度。
                </li>
                <li>
                    <strong>Double:</strong> 如果没有任何一方是 <code>BigDecimal</code>，但有一方是 <code>Double</code> 类型，另一方会被转换为 <code>Double</code>，计算结果为 <code>Double</code>。
                </li>
                <li>
                    <strong>Float:</strong> 如果没有 <code>BigDecimal</code> 或 <code>Double</code>，但有一方是 <code>Float</code> 类型，另一方会被转换为 <code>Float</code>，计算结果为 <code>Float</code>。
                </li>
                <li>
                    <strong>Long:</strong> 如果只有整数类型参与运算，且其中一方是 <code>Long</code>，另一方（如 <code>Integer</code>, <code>Short</code>, <code>Byte</code>）会被提升为 <code>Long</code>，计算结果为 <code>Long</code>。
                </li>
                <li>
                    <strong>Integer (默认整数类型):</strong> 如果所有参与运算的数字都是整型且非<code>Long</code>（即 <code>Integer</code>, <code>Short</code>, <code>Byte</code>），它们将被视为 <code>Integer</code> 进行计算，结果为 <code>Integer</code>。
                </li>
            </ol>
            <p><strong>特殊情况 (<code>+</code> 运算符):</strong></p>
            <p>
                加法运算符 (<code>+</code>) 有一个特殊行为：如果参与运算的任何一方是 <code>String</code> 类型，另一方也会被转换为字符串，整个表达式将执行字符串拼接操作。
            </p>
            <pre><code>// 示例
Expression.parse("1 + 2L").calculate();       // Long + Integer -> Long (结果: 3L)
Expression.parse("1.5f + 2L").calculate();    // Float + Long -> Float (结果: 3.5f)
Expression.parse("1.5d + 2f").calculate();    // Double + Float -> Double (结果: 3.5d)
Expression.parse("'Hello ' + 123").calculate(); // String + Integer -> String (结果: "Hello 123")
</code></pre>
            <pre><code>// 解析并计算
Object result1 = Expression.parse("10 * (5 + 2)").calculate();
System.out.println(result1); // 输出: 70

// 逻辑比较
Object result2 = Expression.parse("(2+1!=2) == true && (100 > 99)").calculate();
System.out.println(result2); // 输出: true</code></pre>

            <h4>三元运算符</h4>
            <p>支持 <code>condition ? value_if_true : value_if_false</code> 语法。</p>
            <pre><code>Object result = Expression.parse("2 > 1 ? 'Yes' : 'No'").calculate();
System.out.println(result); // 输出: Yes</code></pre>

            <!-- 数据访问 -->
            <h3>2. 数据访问</h3>
            <h4>访问数组、List和Map</h4>
            <p>使用 <code>[]</code> 语法访问集合中的元素。</p>
            <pre><code>// 准备数据
Map&lt;String, Object&gt; vars = new HashMap&lt;&gt;();
vars.put("myArray", new int[]{10, 20, 30});
vars.put("myList", Arrays.asList("A", "B", "C"));
vars.put("myMap", Collections.singletonMap("key", "value"));
vars.put("mapKey", "key");

// 访问数组
Object result1 = Expression.parse("myArray[1]").calculate(vars);
System.out.println(result1); // 输出: 20

// 访问List
Object result2 = Expression.parse("myList[2]").calculate(vars);
System.out.println(result2); // 输出: C

// 访问Map（使用字面量或变量作为键）
Object result3 = Expression.parse("myMap['key']").calculate(vars);
System.out.println(result3); // 输出: value

Object result4 = Expression.parse("myMap[mapKey]").calculate(vars);
System.out.println(result4); // 输出: value</code></pre>

            <!-- 对象和类 -->
            <h3>3. 对象和类</h3>
            <h4>方法调用和属性访问</h4>
            <pre><code>// 准备一个自定义对象
public class User {
    public String name = "Gemini";
    public String getName() { return this.name; }
}
Map&lt;String, Object&gt; vars = new HashMap&lt;&gt;();
vars.put("user", new User());

// 访问属性
Object result1 = Expression.parse("user.name").calculate(vars);
System.out.println(result1); // 输出: Gemini

// 调用方法
Object result2 = Expression.parse("user.getName().length()").calculate(vars);
System.out.println(result2); // 输出: 6</code></pre>

            <h4>静态成员访问</h4>
            <p>通过 <code>registerClass</code> 或 <code>@(...)</code> 语法访问静态成员。</p>
            <pre><code>// 方式一: 注册后使用
Expression.registerClass("StringUtil", String.class);
Object result1 = Expression.parse("StringUtil.valueOf(123)").calculate();
System.out.println(result1); // 输出: "123"

// 方式二: 使用完全限定类名
Object result2 = Expression.parse("@(java.lang.Math).max(10, 20)").calculate();
System.out.println(result2); // 输出: 20</code></pre>

            <h4>创建实例和集合</h4>
            <pre><code>// 注册类
Expression.registerClass("Person", Person.class); // 假设Person类已定义

// 创建 new 实例
Object person = Expression.parse("new Person(30)").calculate(); // 假设有 new Person(int age) 构造函数

// 创建数组
Object array = Expression.parse("['a', 'b', 'c']").calculate();

// 创建Set
Object set = Expression.parse("<<'a', 'b', 'a'>>").calculate();
System.out.println(set); // 输出: [a, b] (Set内容)</code></pre>

            <!-- 流程控制 -->
            <h3>4. 流程控制</h3>
            <h4>变量和if-else</h4>
            <pre><code>String script = """
    if (score >= 60) {
        var level = 'Pass';
        return level;
    } else {
        var level = 'Fail';
        return level;
    }
    """;
Operand operand = Expression.parse(script);
Map&lt;String, Object&gt; vars = new HashMap&lt;&gt;();
vars.put("score", 75);
System.out.println(operand.calculate(vars)); // 输出: Pass

vars.put("score", 50);
System.out.println(operand.calculate(vars)); // 输出: Fail</code></pre>

            <h4>For循环</h4>
            <pre><code>String script = """
    var sum = 0;
    for (item in items) {
        sum = sum + item;
    }
    return sum;
    """;
Operand operand = Expression.parse(script);
Map&lt;String, Object&gt; vars = new HashMap&lt;&gt;();
vars.put("items", new int[]{1, 2, 3, 4, 5});
System.out.println(operand.calculate(vars)); // 输出: 15</code></pre>

            <!-- 函数 -->
            <h3>5. 自定义函数</h3>
            <h4>在EL中定义函数</h4>
            <p>使用 <code>function</code> 关键字在脚本中定义函数，支持重载和注释。</p>
            <pre><code>// 注册一个函数
String funcScript = """
# 这是一个加法函数
function my_add(int a, int b) {
    return a + b;
}
""";
Expression.registerFunctionCall(funcScript, "my_scope");

// 在相同的scope中调用它
Operand operand = Expression.parse("my_add(10, 20)", "my_scope");
System.out.println(operand.calculate()); // 输出: 30</code></pre>

            <h4>注册Java方法作为函数</h4>
            <p>可以通过 <code>registerReferenceCall</code> 或 <code>@ReferenceCall</code> 注解将原生Java方法映射为EL函数。</p>
            <pre><code>// 假设有 public static int MyMath.add(int a, int b)
Method method = MyMath.class.getMethod("add", int.class, int.class);
Expression.registerReferenceCall("add_native", method);

Object result = Expression.parse("add_native(5, 3)").calculate();
System.out.println(result); // 输出: 8</code></pre>

            <h4>通过注解自动注册Java方法</h4>
            <p>使用 <code>@ReferenceCall</code> 注解可以更方便地批量注册方法。只需在静态方法上添加该注解，然后调用 <code>scanForReferenceCall</code> 即可。</p>
            <pre><code>// 1. 定义一个包含注解方法的工具类
public class MyFunctions {
    @ReferenceCall("add") // 在EL中暴露为 "add"
    public static int sum(int a, int b) {
        return a + b;
    }

    @ReferenceCall // 如果不指定名称，则使用方法名 "subtract"
    public static int subtract(int a, int b) {
        return a - b;
    }
    
    @ReferenceCall(matrixName = "special_scope") // 可以在特定scope中注册
    public static int multiply(int a, int b) {
        return a * b;
    }
}

// 2. 扫描该类以自动注册所有带注解的方法
Expression.scanForReferenceCall(MyFunctions.class);

// 3. 调用在默认scope中注册的函数
Object result1 = Expression.parse("add(10, 5)").calculate();
System.out.println(result1); // 输出: 15

Object result2 = Expression.parse("subtract(10, 5)").calculate();
System.out.println(result2); // 输出: 5

// 4. 调用在特定scope中注册的函数
Object result3 = Expression.parse("multiply(10, 5)", "special_scope").calculate();
System.out.println(result3); // 输出: 30
</code></pre>

            <!-- 模板 -->
            <h3>6. 模板引擎</h3>
            <p>JfireEL也提供了一个简单的模板引擎，用于字符串渲染。</p>
            <pre><code>import com.jfirer.jfireel.template.Template;

Map&lt;String, Object&gt; vars = new HashMap&lt;&gt;();
vars.put("name", "world");
vars.put("items", Arrays.asList("A", "B"));

// 简单变量插值
String result1 = Template.parse("Hello, ${name}!").render(vars);
System.out.println(result1); // 输出: Hello, world!

// 嵌入控制流脚本
String tpl = "Items:<% for(item in items) { %> ${item}<% } %>";
String result2 = Template.parse(tpl).render(vars);
System.out.println(result2); // 输出: Items: A B</code></pre>
        </div>
    </div>
</body>
</html>
